import { Base64 } from "./core/base64";
import { Helper } from "./core/helper";
import { MemoryStream } from "./core/memory";
import { Morse } from "./core/morse";
import { SM4 } from "./crypto/sm4";
import { ZUC } from "./crypto/zuc";
import { ADLER32, ADLER64 } from "./hash/adler";
import { MD5 } from "./hash/md5";
import { MD6, MD6_512 } from "./hash/md6";
import { KECCAK_224, KECCAK_256, KECCAK_384, KECCAK_512, SHA3_224, SHA3_256, SHA3_384, SHA3_512, SHA3_SHAKE128, SHA3_SHAKE256 } from "./hash/sha3";
import { SM3 } from "./hash/sm3";

export class tonmi {
  static sm4 = new SM4();
  static morse = new Morse();

  public static GetMD5(input: string): string {
    return MD5.Make(Helper.String2Bin(input));
  }
  public static GetMD5Bytes(input: string): number[] {
    return MD5.MakeBytes(Helper.String2Bin(input));
  }
  public static GetSM3(input: string): string {
    return SM3.Make(Helper.String2Bin(input));
  }
  public static GetSha3_512(input: string): string {
    return SHA3_512.JustMake(Helper.String2Bin(input));
  }
  public static GetSHA3_224(input: string): string {
    return SHA3_224.JustMake(Helper.String2Bin(input));
  }
  public static GetSHA3_256(input: string): string {
    return SHA3_256.JustMake(Helper.String2Bin(input));
  }
  public static GetSHA3_384(input: string): string {
    return SHA3_384.JustMake(Helper.String2Bin(input));
  }
  public static GetSHA3_512(input: string): string {
    return SHA3_512.JustMake(Helper.String2Bin(input));
  }
  public static GetSHA3_SHAKE128(input: string): string {
    return SHA3_SHAKE128.JustMake(Helper.String2Bin(input));
  }
  public static GetSHA3_SHAKE256(input: string): string {
    return SHA3_SHAKE256.JustMake(Helper.String2Bin(input));
  }
  public static GetKECCAK_224(input: string): string {
    return KECCAK_224.JustMake(Helper.String2Bin(input));
  }
  public static GetKECCAK_256(input: string): string {
    return KECCAK_256.JustMake(Helper.String2Bin(input));
  }
  public static GetKECCAK_384(input: string): string {
    return KECCAK_384.JustMake(Helper.String2Bin(input));
  }
  public static GetKECCAK_512(input: string): string {
    return KECCAK_512.JustMake(Helper.String2Bin(input));
  }
  public static GetADLER32(input: string): string {
    return ADLER32.JustMake(Helper.String2Bin(input));
  }
  public static GetADLER64(input: string): string {
    return ADLER64.JustMake(Helper.String2Bin(input));
  }
  public static GetMD6(input: string): string {
    return MD6.JustMake(Helper.String2Bin(input));
  }
  public static GetMD6_512(input: string): string {
    return MD6_512.JustMake(Helper.String2Bin(input));
  }
  public static EncryptSM4(input: string, key: string) {
    tonmi.sm4.New();
    tonmi.sm4.SetKey(tonmi.GetMD5Bytes(key));
    return tonmi.Base64EncodeBytes(this.sm4.Encrypt(Helper.String2Bin(input)));
  }
  public static DecryptSM4(input: string, key: string) {
    tonmi.sm4.New();
    tonmi.sm4.SetKey(tonmi.GetMD5Bytes(key));
    let data = this.sm4.Decrypt(tonmi.Base64Decode2Bytes(input));
    return Helper.Bin2Utf8(data, 0, data.length);
  }
  public static GetZUC(iv: string, key: string) {
    let zuc = new ZUC();
    zuc.Init(tonmi.GetMD5Bytes(key), tonmi.GetMD5Bytes(key));
    return zuc;
  }
  public static Base64Encode(text: string) {
    return tonmi.Base64EncodeBytes(Helper.String2Bin(text));
  }
  public static Base64EncodeBytes(data: number[]) {
    let output = "";
    let base64 = new Base64(128);
    let len;
    for (let i = 0; i < data.length; i += base64.EncodeMaxLength) {
      len = base64.Encode(data, i, base64.EncodeMaxLength);
      if (len > 0) output += Helper.Bin2Ascii(base64.Buffer, 0, len);
    }
    return output;
  }
  public static Base64Decode(base64text: string) {
    let output = "";
    let base64 = new Base64(128);

    let data = Helper.String2Bin(base64text);
    let len;

    for (let i = 0; i < data.length; i += base64.DecodeMaxLength) {
      len = base64.Decode(data, i, base64.DecodeMaxLength);
      if (len > 0) output += Helper.Bin2Utf8(base64.Buffer, 0, len);
    }
    return output;
  }
  public static Base64Decode2Bytes(base64text: string) {
    var output = new MemoryStream();
    let base64 = new Base64(128);

    let data = Helper.String2Bin(base64text);
    let len;

    for (let i = 0; i < data.length; i += base64.DecodeMaxLength) {
      len = base64.Decode(data, i, base64.DecodeMaxLength);
      if (len > 0) output.Write(base64.Buffer, 0, len);
    }
    return output.ToArrary();
  }
  public static EncodeMorse(msg: string): number[] {
    return this.morse.Encode(msg, msg.length);
  }
  public static DecodeMorse(morse_bytes: number[]): string {
    return this.morse.Decode(morse_bytes, morse_bytes.length);
  }
  public static EncodeHex(data: number[]): string {
    return Helper.ToHex(data);
  }
  public static DecodeHex(hexstring: string): number[] {
    return Helper.ToBytes(hexstring);
  }
}